package gruppenkalenderProjekt.db;

import gruppenkalenderProjekt.data.Kalender;
import gruppenkalenderProjekt.data.KalenderImpl;
import java.rmi.RemoteException;
import java.sql.*;
import java.util.Vector;

// <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
// #[regen=yes,id=DCE.E4FB643D-0A8F-296D-1F21-C34875443E58]
// </editor-fold>
/** Agiert als Schnittstelle zur Kalender Tabelle der Datenbank.
 * Beinhaltet die SQL Statements zur Auslesung und Datenmanipulation.
 *
 * @author  Rathke,Thies
 * @coauthor Gruppe 2
 */
public class KalenderMapper {

    private static KalenderMapper kalenderMapper = null;

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.D53EA1F8-0760-1F5D-82E5-17DC3B340E03]
    // </editor-fold> 
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.5BDAF9D5-6BF7-E8C3-4DD2-202687A51D89]
    // </editor-fold> 
    protected KalenderMapper() {
    }

    /**
     * Diese statische Methode kann aufgrufen werden durch
     * <code>KalenderMapper.kalenderMapper()</code>. Sie stellt die
     * Singleton-Eigenschaft sicher, indem Sie dafür sorgt, daß nur eine einzige
     * Instanz von <code>KalenderMapper</code> existiert.<p>
     *
     * <b>Fazit:</b> KalenderMapper sollte nicht mittels <code>new</code>
     * instantiiert werden, sondern stets durch Aufruf dieser statischen Methode.
     *
     * @return DAS <code>KalenderMapper</code>-Objekt.
     * @see kalenderMapper
     */
    public static KalenderMapper kalenderMapper() {
        // Wenn noch kein Kalender-Mapper existiert wird dieser jetzt erstellt
        if (kalenderMapper == null) {
            kalenderMapper = new KalenderMapper();
        }
        System.out.print("Kalender-Mapper erstellt...");
        return kalenderMapper;
    }

    /**Methode die alle Kalender findet und zurueck gibt
     *
     * @return result Vector mit allen Kalendern
     */
    public Vector<Kalender> findeAlleKalender() {            //Ist das mit den While-Schleifen falsch??? wird es dann in der richtigen Reihenfolge zurückgegeben???
        //Ein Connection Objekt wird erstellt und Datenbankverbindung wird mitgegeben
        Connection con = DBConnection.connection();
        //Ein Vektor vom Typ Kategorie wird erstellt
        Vector<Kalender> result = new Vector<Kalender>();

        try {
            //leeres Statement erstellen
            Statement stmt = con.createStatement();
            //Neues ResultSet erstellen und Datenbankinhalt in dieser ablegen
            ResultSet rs = stmt.executeQuery(
                    "SELECT * FROM kalender ");
            // Solange weitere Datensätze im Result Set vorhanden
            while (rs.next()) {
                try {
                    //Lokales Objekt zum Zwischenspeichern erstellen
                    Kalender k = new KalenderImpl();
                    k.setKalenderID(rs.getInt("k_ID"));
                    k.setName(rs.getString("name"));

                    result.addElement(k);

                } catch (RemoteException ex) {
                    ex.printStackTrace();
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }

        return result;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.804BB2D4-BD87-A40C-A132-296DFE872640]
    // </editor-fold>
    /**Methode die einen Kalender mit einer uebergebenen ID findet
     *
     * @param k_ID die ID des zu findenden Kalenders
     * @return k ein Kalenderobjekt
     */
    public Kalender findeKalenderMitID(int k_ID) {
        Connection con = DBConnection.connection();                 //DB verbindung
        try {
            Statement stmt = con.createStatement();                  //leeres Statement anlegen --> jdbc!
            ResultSet rs = stmt.executeQuery( // statement füllen und ausführen an DB
                    "SELECT * FROM kalender " +
                    "WHERE k_ID=" + k_ID);

            if (rs.next()) {
                try {
                    Kalender k = new KalenderImpl();
                    k.setKalenderID(rs.getInt("k_ID"));
                    k.setName(rs.getString("name"));
                    return k;

                } catch (RemoteException ex) {
                    ex.printStackTrace();
                    return null;
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return null;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.FCA2D9B9-D94D-073D-9FC9-A092C31D2E56]
    // </editor-fold>
    /**Legt einen neuen Kalendereintrag an
     *
     * @param kalender der anzulegende Kalender
     * @return k ein Kalenderobjekt
     */
    public Kalender insert(Kalender kalender) {
        Connection con = DBConnection.connection();         //connection holen

        try {
            Statement stmt = con.createStatement();             //neues statement anlegen


            stmt.executeUpdate("INSERT INTO kalender (name) " + //einfügen des neuen objekts in db
                    "VALUES ('" +
                    kalender.getName() + "')");

            try {
                stmt = con.createStatement();

                ResultSet rs = stmt.executeQuery("SELECT k_ID FROM kalender WHERE kalender.name = '" + kalender.getName() + "'");

                if (rs.next()) {
                    kalender.setKalenderID(rs.getInt("k_ID"));
                }

                // Müsste hier noch das INSERT für Besitz und Zugehörigkeit rein????
                //Zwischentabelle Besitz fuellen
                stmt = con.createStatement();
                stmt.executeUpdate("INSERT INTO besitz (k_ID, b_ID) " + //einfügen des neuen objekts in db
                        "VALUES ('" + kalender.getKalenderID() +
                        "','" + kalender.getBesitzer().getBenutzerID() + "')");

                //Zwischentabelle zugehoerigkeit in schleife fuellen,
                //vlt. geht es auch in einem SQL Statement ?
                for (int i = 0; i < kalender.getBenutzer().size(); i++) {
                    stmt = con.createStatement();
                    stmt.executeUpdate("INSERT INTO zugehoerigkeit (k_ID, b_ID) " + //einfügen des neuen objekts in db
                            "VALUES ('" + kalender.getKalenderID() +
                            "','" + kalender.getBenutzer().elementAt(i).getBenutzerID() + "')");

                }


            } catch (SQLException e3) {
                e3.printStackTrace();
            }
        } catch (RemoteException ex) {
            ex.printStackTrace();
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return kalender; //eingefügtes Objekt wird wieder zurückgegeben
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.9923659C-73CD-A658-2497-343332BC49E2]
    // </editor-fold>
    /**Loescht einen Kalender aus der DB
     *
     * @param kalender  der zu loeschende Kalender
     */
    public void delete(Kalender kalender) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM kalender " +
                    "WHERE k_ID=" + kalender.getKalenderID());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

    /**loescht den Besitzer eines Kalenders
     * 
     * @param kalender der Kalender aus dem der Besitzer geloescht werden soll
     */
    public void deleteBesitzerVonKalender(Kalender kalender) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM besitz " +
                    "WHERE k_ID=" + kalender.getKalenderID());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

    /**Loescht alle Benutzer eines Kalenders
     *
     * @param kalender der Kalender aus dem die Benutzer geloescht werden sollen
     */
    public void deleteAlleBenutzerVonKalender(Kalender kalender) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            stmt.executeUpdate("DELETE FROM zugehoerigkeit " +
                    "WHERE k_ID=" + kalender.getKalenderID());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.6DB62332-50C8-A260-5F5D-E6522C12414B]
    // </editor-fold>
    /**aktualisiert einen Kalender
     *
     * @param kalender der zu aktualisierende Kalender
     * @return k ein Kalenderobjekt
     */
    public Kalender update(Kalender kalender) { //wo wird Besitz und Zugehörigkeit geupdatet???
        Connection con = DBConnection.connection();
        try {
            Statement stmt = con.createStatement();

            stmt.executeUpdate("UPDATE kalender " +
                    "SET " +
                    "name='" + kalender.getName() +
                    "' WHERE k_ID=" + kalender.getKalenderID());


            //zwischentabelle komplett loeschen
            this.deleteAlleBenutzerVonKalender(kalender);


            //Zwischentabelle zugehoerigkeit in schleife fuellen,
            //vlt. geht es auch in einem SQL Statement ?
            for (int i = 0; i < kalender.getBenutzer().size(); i++) {
                stmt = con.createStatement();
                stmt.executeUpdate("INSERT INTO zugehoerigkeit (k_ID, b_ID) " + //einfügen des neuen objekts in db
                        "VALUES ('" + kalender.getKalenderID() +
                        "','" + kalender.getBenutzer().elementAt(i).getBenutzerID() + "')");

            }

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return kalender; //geändertes Objekt wird wieder zurückgegeben
    }

    /** Methode die alle Kalender eines Benutzer findet
     * @param b_id die ID des Benutzers
     * @return ergebnis Vector mit allen Kalenderobjekten
     */
    public Vector<Kalender> getAlleKalendervonBenutzer(int b_id) {

        // Lokaler Vektor mit der Bezeichnung ergenis erstellt
        Vector<Kalender> ergebnis = new Vector<Kalender>();

        /*Ein Connection Objekt mit der Bezeichnung con wird erstellt und diesem
         *die Datenbankverbindung übergeben
         */
        Connection con = DBConnection.connection();

        try {
            // Leeres SQL-Statement (JDBC) anlegen
            Statement stmt = con.createStatement();

            // Statement befüllen und als Abfrage an die DB schicken
            ResultSet rs = stmt.executeQuery("SELECT * FROM zugehoerigkeit WHERE b_ID='" + b_id + "'");

            /*Füge dem Vektor ergebnis mit der Methode "addElement" vollständige Kalenderobjekte hinzu,
             * von den Kalendern, die der Benutzer benutzt. Ermöglicht wird dies dadurch, dass im ResultSet
             * rs zum aktuellen Zeitpunkt nur die KalenderID's vorhanden sind welche der mitgegebenen BenuzterID
             * entsprechen (siehe Datenbankabfrage). Beim befüllen des Vektors wird die Methode findeKalenderMitID
             * ausgeführt und dieser als Parameter durch "rs.getInt("k_ID")" nur die k_ID's mitgegeben, welche
             * im Resultset rs stehen.
             *
             */
            while (rs.next()) {

                ergebnis.addElement(this.findeKalenderMitID(rs.getInt("k_ID")));
            }
            return ergebnis;



        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        return null;
    }
}

